package org.erp.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.erp.common.context.StockLockContext;
import org.erp.common.enums.DeviceInventoryEvent;
import org.erp.common.page.PageQueryModel;
import org.erp.product.domain.dto.*;
import org.erp.product.domain.entity.ConnectLog;
import org.erp.product.domain.entity.ProductInfo;
import org.erp.product.domain.entity.RepairInfo;
import org.erp.product.domain.vo.ConnectLogVo;
import org.erp.product.infrastructure.config.ConnectStateFlow;
import org.erp.product.infrastructure.convert.ConnectConvert;
import org.erp.product.infrastructure.enums.*;
import org.erp.product.infrastructure.exception.ProductException;
import org.erp.product.infrastructure.mapper.ConnectLogMapper;
import org.erp.product.infrastructure.mq.service.ProductRabbitService;
import org.erp.product.router.DeviceEventRouter;
import org.erp.product.service.ConnectLogService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 接驳记录服务实现层
 *
 * @author libin
 * @version 1.0
 * @description: 接驳记录服务实现层
 * @date 2025/11/13 16:25
 **/
@Log4j2
@Service
@AllArgsConstructor
public class ConnectLogServiceImpl extends ServiceImpl<ConnectLogMapper, ConnectLog> implements ConnectLogService {

    private final ConnectConvert connectConvert;

    private final ProductRabbitService productRabbitService;

    private final DeviceEventRouter deviceEventRouter;

    @Override
    public PageQueryModel<ConnectLogVo> pageList(ConnectLogQueryDto connectLogQueryDto) {
        Page<ConnectLog> page = this.page(connectLogQueryDto.buildPage()
                , new QueryWrapper<ConnectLog>().lambda()
                        .eq(ConnectLog::getTransferType, connectLogQueryDto.getTransferType())
                        .eq(null != connectLogQueryDto.getNewStatus(), ConnectLog::getNewStatus, connectLogQueryDto.getNewStatus())
                        .eq(null != connectLogQueryDto.getTenantId(), ConnectLog::getTenantId, connectLogQueryDto.getTenantId())
                        .ge(null != connectLogQueryDto.getStartTime(), ConnectLog::getCreateTime, connectLogQueryDto.getStartTime())
                        .le(null != connectLogQueryDto.getEndTime(), ConnectLog::getCreateTime, connectLogQueryDto.getEndTime()));
        return PageQueryModel.of(page.getPages(), page.getRecords().stream()
                .map(connectConvert::convertVo).toList());
    }


//    @StockLockBatch(directIds = true, busyKey = ProductConstant.PRODUCT_BUSY_CONNECT_LOGS)
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public void overrule(List<Long> ids) {
//        List<ConnectLog> connectLogList = searchAndVerify(ids, ConnectEventEnum.OVERRULE);
    // 1. 数据分流
//        triage(connectLogList
//                , DeviceInventoryEvent.REJECT
//                , ConnectEventEnum.OVERRULE
//                , null
//                , null);
//    }
//
//    @StockLockBatch(directIds = true, busyKey = ProductConstant.PRODUCT_BUSY_CONNECT_LOGS)
//    @Override
//    public void quash(List<Long> ids) {
//        List<ConnectLog> connectLogList = searchAndVerify(ids, ConnectEventEnum.QUASH);
//        triage(connectLogList
//                , DeviceInventoryEvent.CANCEL_REJECT
//                , ConnectEventEnum.QUASH
//                , InspectionStatusEnum.CONNECTED
//                , RepairStatusEnum.CONNECTED);
//    }
    @Override
    public List<DickerDto> checkForsake(List<DickerDto> dickerDtoList) {
        Set<Long> stockIds = dickerDtoList.stream()
                .map(DickerDto::getStockId).collect(Collectors.toSet());
        List<ConnectLog> list = this.list(new QueryWrapper<ConnectLog>().lambda()
                .in(ConnectLog::getStockId, stockIds)
                .eq(ConnectLog::getNewStatus, ConnectStatusEnum.WAITING_FOR_CONNECTION.getCode()));
        Set<Long> searchStockIds = list.stream().map(ConnectLog::getStockId).collect(Collectors.toSet());
        return dickerDtoList.stream()
                .filter(s -> !searchStockIds.contains(s.getStockId())).toList();
    }

    /**
     * 数据分流处理
     *
     * @param connectLogList
     */
    public ConnectLogTriageDto triage(List<ConnectLog> connectLogList) {
        List<ConnectLog> warehouseList = new ArrayList<>();
        List<ConnectLog> nonWarehouseList = new ArrayList<>();
        for (ConnectLog c : connectLogList) {
            if (SourceChannelEnum.WAREHOUSE.getCode().equals(c.getSourceChannel())) {
                warehouseList.add(c);
            } else {
                nonWarehouseList.add(c);
            }
        }
        return ConnectLogTriageDto.build(warehouseList,nonWarehouseList);
    }

    /**
     * 更改接驳列表状态
     *
     * @param connectLogList
     * @param connectEventEnum
     */
    @Override
    public void updateStatus(List<ConnectLog> connectLogList, ConnectEventEnum connectEventEnum) {
        //更改接驳状态
        connectLogList.forEach(w -> {
            ConnectStatusEnum nextStatus = ConnectStateFlow.next(ConnectStatusEnum.getByCode(w.getNewStatus()), connectEventEnum);
            w.setOldStatus(w.getNewStatus());
            w.setNewStatus(nextStatus.getCode());
        });
        this.baseMapper.updateBatchById(connectLogList);
    }

    /**
     * 执行通知仓库
     *
     * @param warehouseList
     * @param deviceInventoryEvent
     */
    @Override
    public void handleWarehouse(List<ConnectLog> warehouseList, DeviceInventoryEvent deviceInventoryEvent) {
        StockLockContext.setHasExternal(true);
        productRabbitService.sendActionMessage(warehouseList, deviceInventoryEvent);
    }

    /**
     * 执行质检状态处理
     *
     * @param productInfoList
     * @param connectEventEnum
     * @param inspectionTransferStatusEnum
     */
    @Override
    public void handleInspection(List<ProductInfo> productInfoList, ConnectEventEnum connectEventEnum, InspectionStatusEnum inspectionTransferStatusEnum) {
//        if (ConnectEventEnum.CONNECTION.equals(connectEventEnum)) {
//            productInfoList.forEach(p -> {
//                p.setRepairStatus(RepairStatusEnum.CONNECTED.getCode());
//                p.setInspectionStatus(null == inspectionTransferStatusEnum ? -1 : inspectionTransferStatusEnum.getCode());
//            });
//        }
//        if (ConnectEventEnum.OVERRULE.equals(connectEventEnum)) {
//            productInfoList.forEach(p -> {
//                p.setRepairStatus(RepairStatusEnum.DISMISSED.getCode());
//                p.setInspectionStatus(null == inspectionTransferStatusEnum ? -1 : inspectionTransferStatusEnum.getCode());
//            });
//        }
//        productInfoMapper.updateBatchById(productInfoList);
    }

    /**
     * 执行维修状态处理
     *
     * @param productInfoList
     * @param connectEventEnum
     * @param repairTransferStatusEnum
     */
    @Override
    public void handleRepair(List<ProductInfo> productInfoList, ConnectEventEnum connectEventEnum, RepairStatusEnum repairTransferStatusEnum) {
//        if (ConnectEventEnum.CONNECTION.equals(connectEventEnum)) {
//            productInfoList.forEach(p -> {
//                p.setInspectionStatus(InspectionStatusEnum.CONNECTED.getCode());
//                p.setRepairStatus(null == repairTransferStatusEnum ? -1 : repairTransferStatusEnum.getCode());
//            });
//        }
//        if (ConnectEventEnum.OVERRULE.equals(connectEventEnum)) {
//            productInfoList.forEach(p -> {
//                p.setInspectionStatus(InspectionStatusEnum.DISMISSED.getCode());
//                p.setRepairStatus(null == repairTransferStatusEnum ? -1 : repairTransferStatusEnum.getCode());
//            });
//        }
//        productInfoMapper.updateBatchById(productInfoList);
    }

//    /**
//     * 添加操作日志
//     *
//     * @param list
//     * @param oldStatus
//     * @param newStatus
//     */
//    private void saveTransferLog(List<ConnectLog> list, Integer oldStatus, Integer newStatus, ConnectEventEnum connectEventEnum) {
//        List<TransferLog> transferLogList = list.stream().map(c -> {
//            TransferLog transferLog = new TransferLog();
//            transferLog.setStockId(c.getStockId());
//            transferLog.setEventCode(EventCodeEnum.CONNECT.getCode());
//            transferLog.setEventName(connectEventEnum.getMessage());
//            return TransferLog.getOverruleTransferLog(oldStatus, newStatus, c, transferLog);
//        }).toList();
//        transferLogService.saveBatch(transferLogList);
//    }

    @Override
    public List<ConnectLog> searchAndVerify(List<Long> ids, ConnectEventEnum connectEventEnum) {
        List<ConnectLog> connectLogList = this.listByIds(ids);
        for (ConnectLog connectLog : connectLogList) {
            try {
                ConnectStateFlow.next(ConnectStatusEnum.getByCode(connectLog.getNewStatus()), connectEventEnum);
            } catch (Exception e) {
                throw new ProductException("接驳操作事件id为: " + connectLog.getId() + " 状态不允许执行该操作");
            }
        }
        return connectLogList;
    }

    @Override
    public void repairSaveBatch(TransferDto transferDto, List<RepairInfo> repairInfoList, TransferLogAddDto transferLogAddDto) {
        List<ConnectLog> list = new ArrayList<>();
        repairInfoList.forEach(r -> {
            ConnectLog connectLog = new ConnectLog();
            connectLog.setStockId(r.getStockId());
            connectLog.setProductName(r.getProductName());
            connectLog.setBrandId(r.getBrandId());
            connectLog.setCategoryId(r.getCategoryId());
            connectLog.setModelId(r.getModelId());
            connectLog.setSeriesId(r.getSeriesId());
            connectLog.setLevelId(r.getLevelId());
            connectLog.setProductImei(r.getProductImei());
            connectLog.setProductCode(r.getProductCode());
            connectLog.setProductColor(r.getProductColor());
            connectLog.setProductStorage(r.getProductStorage());
            connectLog.setTenantId(r.getTenantId());
            connectLog.setTenantName(r.getTenantName());
            connectLog.setSourceChannel(transferDto.getSourceChannel());
            connectLog.setTransferType(transferDto.getTransferType());
            connectLog.setOperationId(transferDto.getOperationId());
            connectLog.setOperationName(transferDto.getOperationName());
            connectLog.setTransferId(transferDto.getTransferId());
            connectLog.setTransferName(transferDto.getTransferName());
            connectLog.setDeptId(transferDto.getDeptId());
            connectLog.setDeptName(transferDto.getDeptName());
            connectLog.setCostPrice(r.getCostPrice());
            if (TransferTypeEnum.DICKER_TRANSFER.getCode().equals(transferDto.getTransferType())) {
                transferDto.getDickerDtoList().forEach(d -> {
                    if (d.getStockId().equals(r.getStockId())) {
                        connectLog.setDickerPrice(d.getDickerPrice());
                    }
                });
            } else {
                connectLog.setDickerPrice(0);
            }
            connectLog.setOldStatus(-1);
            connectLog.setOldStatus(ConnectStatusEnum.WAITING_FOR_CONNECTION.getCode());
            connectLog.setCreateBy("");
            list.add(connectLog);
        });
        transferLogAddDto.setConnectOldStatus(-1);
        transferLogAddDto.setConnectNewStatus(ConnectStatusEnum.WAITING_FOR_CONNECTION.getCode());
        this.baseMapper.saveBatch(list);
    }

    @Override
    public void inspectionSaveBatch(TransferDto transferDto, List<ProductInfo> productInfoList, TransferLogAddDto transferLogAddDto) {
        List<ConnectLog> list = new ArrayList<>();
        productInfoList.forEach(i -> {
            ConnectLog connectLog = new ConnectLog();
            connectLog.setStockId(i.getStockId());
            connectLog.setProductName(i.getProductName());
            connectLog.setBrandId(i.getBrandId());
            connectLog.setCategoryId(i.getCategoryId());
            connectLog.setModelId(i.getModelId());
            connectLog.setSeriesId(i.getSeriesId());
            connectLog.setLevelId(i.getLevelId());
            connectLog.setProductImei(i.getProductImei());
            connectLog.setProductCode(i.getProductCode());
            connectLog.setProductColor(i.getProductColor());
            connectLog.setProductStorage(i.getProductStorage());
            connectLog.setTenantId(i.getTenantId());
            connectLog.setTenantName(i.getTenantName());
            connectLog.setSourceChannel(transferDto.getSourceChannel());
            connectLog.setTransferType(transferDto.getTransferType());
            connectLog.setOperationId(transferDto.getOperationId());
            connectLog.setOperationName(transferDto.getOperationName());
            connectLog.setTransferId(transferDto.getTransferId());
            connectLog.setTransferName(transferDto.getTransferName());
            connectLog.setDeptId(transferDto.getDeptId());
            connectLog.setDeptName(transferDto.getDeptName());
            connectLog.setCostPrice(i.getCostPrice());
            if (TransferTypeEnum.DICKER_TRANSFER.getCode().equals(transferDto.getTransferType())) {
                transferDto.getDickerDtoList().forEach(d -> {
                    if (d.getStockId().equals(i.getStockId())) {
                        connectLog.setDickerPrice(d.getDickerPrice());
                    }
                });
            } else {
                connectLog.setDickerPrice(0);
            }
            connectLog.setOldStatus(-1);
            connectLog.setOldStatus(ConnectStatusEnum.WAITING_FOR_CONNECTION.getCode());
            connectLog.setCreateBy("");
            list.add(connectLog);
        });
        transferLogAddDto.setConnectOldStatus(-1);
        transferLogAddDto.setConnectNewStatus(ConnectStatusEnum.WAITING_FOR_CONNECTION.getCode());
        this.baseMapper.saveBatch(list);
    }
}
